package top.infopub.mgr.fia.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.infopub.dto.fia.BudgetDto;
import top.infopub.dto.fia.BudgetSubDto;
import top.infopub.dto.fia.OutConReviewAmtDto;
import top.infopub.enums.fia.FiaProcessDetailTypeEnum;
import top.infopub.enums.mkt.ProProcesssStatusEnum;
import top.infopub.generic.GenericDao;
import top.infopub.generic.GenericServiceImpl;
import top.infopub.mgr.common.vo.RspVo;
import top.infopub.mgr.exception.FlowProcessException;
import top.infopub.mgr.fia.dao.BudgetDao;
import top.infopub.mgr.fia.dao.BudgetSubDao;
import top.infopub.mgr.fia.dao.CommonDao;
import top.infopub.mgr.fia.domain.BudgetSummaryDomain;
import top.infopub.mgr.fia.jsonvo.BudgetJsonVo;
import top.infopub.mgr.fia.service.BudgetService;
import top.infopub.mgr.fia.service.FiaProcessManageService;
import top.infopub.mgr.fia.vo.BudgetSummaryVo;
import top.infopub.mgr.flow.service.OAFlowService;
import top.infopub.mgr.hr.dao.OrgInfoDao;
import top.infopub.mgr.hr.dao.StaffInfoDao;
import top.infopub.model.common.ProInfo;
import top.infopub.model.fia.Budget;
import top.infopub.model.fia.BudgetSub;
import top.infopub.model.fia.BudgetTypes;
import top.infopub.model.hr.StaffInfo;
import top.infopub.security.util.SessionUserUtils;
import top.infopub.security.vo.AuthorizationVO;
import top.infopub.util.IdFactory;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
public class BudgetServiceImpl extends GenericServiceImpl<Budget, String> implements
		BudgetService {
	@Autowired
	private BudgetDao budgetDao;

	@Autowired
	private BudgetSubDao budgetSubDao;

	@Autowired
	private CommonDao commonDao;

	@Autowired
	private StaffInfoDao staffInfoDao;

	@Autowired
	private OrgInfoDao orgInfoDao;

	@Autowired
	private OAFlowService oaFlowService;

	@Autowired
	private FiaProcessManageService fiaProcessManageService;
	
	@Override
	public GenericDao<Budget, String> getDao() {
		return budgetDao;
	}

    @Override
    public Page<BudgetSummaryDomain> selectPageByDomainWhere(Page<BudgetSummaryDomain> page,
															 BudgetSummaryVo budgetSummaryVo) {
        PageHelper.startPage(page.getPageNum(), page.getPageSize());
        return (Page<BudgetSummaryDomain>)budgetDao.selectByDomainWhere(budgetSummaryVo);
    }

	@Override
	public BudgetJsonVo queryDetailById(String id) {
		BudgetJsonVo budgetJson = new BudgetJsonVo();
		if (StringUtils.isNotBlank(id)) {
			//基础信息
			BudgetDto budgetDto = budgetDao.queryDetailById(id);
			budgetJson.setInfo(budgetDto);

			//基础信息列表
			List<OutConReviewAmtDto> infoList = budgetDao.querySumOutConReviewAmtList(budgetDto.getProCode());
			budgetJson.setInfoList(infoList);

			//详情列表
			List<BudgetSubDto> detailList = getBudgetSubList(id);
			budgetJson.setDetailList(detailList);
		} else {
			//项目信息列表
			List<ProInfo> proInfoList = commonDao.queryProCodeAndNameList("BPA_CONTRACT_BPAREVIEW");
			budgetJson.setProInfoList(proInfoList);
		}
		return budgetJson;
	}

	@Override
	public BudgetJsonVo queryDetail(String proCode) {
		BudgetJsonVo budgetJson = new BudgetJsonVo();
		AuthorizationVO vo = SessionUserUtils.getSessionAttributeForUserDtl();
		StaffInfo staffInfo = staffInfoDao.selectByPrimaryKey(vo.getHrStaffId());
		String hrOrgId = "";
		if (staffInfo != null) {
//			OrgInfo orgInfo = orgInfoDao.selectByPrimaryKey(staffInfo.getPkOrg());
//			if (orgInfo != null) {
//				hrOrgId = orgInfo.getId();
//			}
			hrOrgId = staffInfo.getPkOrg();
		}
		if (StringUtils.isBlank(hrOrgId)) throw new FlowProcessException("未绑定公司，无法进行新增查询~");
		int year = Calendar.getInstance().get(Calendar.YEAR);
		String budgetYear = String.valueOf(year);
		Budget budget = budgetDao.queryByUniWhere(proCode, budgetYear, hrOrgId);
		String id = null;
		if (budget != null) {
			//基础信息
			id = budget.getId();
			BudgetDto budgetDto = budgetDao.queryDetailById(id);
			budgetJson.setInfo(budgetDto);
		} else {
			BudgetDto dto = new BudgetDto();
			dto.setBudgetYear(budgetYear);
			dto.setHrOrgId(hrOrgId);
			budgetJson.setInfo(dto);
		}
		//基础信息列表
		List<OutConReviewAmtDto> infoList = budgetDao.querySumOutConReviewAmtList(proCode);
		budgetJson.setInfoList(infoList);
		//详情列表
		List<BudgetSubDto> detailList = getBudgetSubList(id);
		budgetJson.setDetailList(detailList);
		return budgetJson;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public RspVo edit(BudgetJsonVo budgetJson, Integer submitType, AuthorizationVO vo) {
		Budget tmpBud = new Budget();
		Budget budget = new Budget();
		BudgetDto budgetDto = budgetJson.getInfo();
		BeanUtils.copyProperties(budgetDto, budget);
		budget.setUptBy(vo.getId());
		budget.setUptTime(new Date());
		if (StringUtils.isBlank(budget.getHrOrgId())) {
			StaffInfo staffInfo = staffInfoDao.selectByPrimaryKey(vo.getHrStaffId());
			String hrOrgId = "";
			if (staffInfo != null) {
//				OrgInfo orgInfo = orgInfoDao.selectByPrimaryKey(staffInfo.getPkOrg());
//				if (orgInfo != null) {
//					hrOrgId = orgInfo.getId();
//				}
				hrOrgId = staffInfo.getPkOrg();
			}
			if (StringUtils.isBlank(hrOrgId)) throw new FlowProcessException("未绑定公司，无法进行新增查询~");
			budget.setHrOrgId(hrOrgId);
		}
		if (StringUtils.isBlank(budget.getBudgetYear())) {
			int year = Calendar.getInstance().get(Calendar.YEAR);
			String budgetYear = String.valueOf(year);
			budget.setBudgetYear(budgetYear);
		}

		if (StringUtils.isNotBlank(budgetDto.getId())) {
			//校验数据是否存在
			tmpBud = budgetDao.selectByPrimaryKey(budgetDto.getId());
			if (tmpBud == null) return RspVo.getFailureResponse(400, "月度资金计划数据不存在");
			//判断审批状态
			if (StringUtils.isNotBlank(tmpBud.getProcessStatus())
					&& (StringUtils.equals(ProProcesssStatusEnum.PRO_STATUS1.getCode(), tmpBud.getProcessStatus())
					|| StringUtils.equals(ProProcesssStatusEnum.PRO_STATUS9.getCode(), tmpBud.getProcessStatus()))) {
				return RspVo.getFailureResponse(400, "审批状态不正确，操作失败");
			}
			budgetDao.updateByIdSelective(budget);
		} else {
			budget.setAddBy(vo.getId());
			budget.setAddTime(new Date());
			budget.setCodes(IdFactory.getUUIDUpper());
			budgetDao.insertSelective(budget);
		}

		//保存详情信息
		List<BudgetSubDto> detailList = budgetJson.getDetailList();
		if (detailList != null && detailList.size() > 0) {
			int sortNo = 1;
			for (BudgetSubDto bsd : detailList) {
				//详情信息
				if (bsd == null) continue;
				BudgetSub bs = new BudgetSub();
				BeanUtils.copyProperties(bsd, bs);
				bs.setUptBy(vo.getId());
				bs.setUptTime(new Date());
				bs.setSortNo(sortNo);
				bs.setBudgetId(budget.getId());
				//保存或更新详情信息
				if (StringUtils.isNotBlank(bs.getId())) {
					budgetSubDao.updateByIdSelective(bs);
				} else {
					bs.setAddBy(vo.getId());
					bs.setAddTime(new Date());
					budgetSubDao.insertSelective(bs);
				}
				sortNo++;
			}
		}

		if (submitType == 1) {
			if (StringUtils.isNotBlank(tmpBud.getOaId())) {
				oaFlowService.finishOA(tmpBud.getOaId());
			}
			BudgetJsonVo tmpJson = queryDetailById(budget.getId());
			String detailJson = JSON.toJSONString(tmpJson);
			fiaProcessManageService.sendProcess(FiaProcessDetailTypeEnum.PRO_NODE_TYPE1, detailJson, budget.getId(), budget.getProCode(), vo);
		}
		return RspVo.getSuccessResponse();
	}

	/**
	 * 分类详情整合
	 * @param budgetId
	 * @return
	 */
	private List<BudgetSubDto> getBudgetSubList(String budgetId) {
		//查询明细list
		List<BudgetSubDto> detailList = null;
		if (StringUtils.isNotBlank(budgetId)) {
			detailList = budgetSubDao.querySubDetailByBudgetId(budgetId);
			if (detailList != null && detailList.size() > 0) return detailList;
		}
		List<BudgetTypes> typesList = budgetSubDao.queryTypesByParentId("0");
		if (typesList != null && typesList.size() > 0) {
			List<BudgetSubDto> result = new ArrayList<>();
			BudgetSubDto detail;
			for (BudgetTypes parent : typesList) {
				if (parent == null) continue;
				detail = setTypesInfo(parent, "0");
				result.add(detail);
				List<BudgetTypes> nextList = budgetSubDao.queryTypesByParentId(parent.getId());
				if (nextList != null && nextList.size() > 0) {
					for (BudgetTypes chren : nextList) {
						if (chren == null) continue;
						detail = setTypesInfo(chren, parent.getTypeId());
						result.add(detail);
						List<BudgetTypes> lowestList = budgetSubDao.queryTypesByParentId(chren.getId());
						if (lowestList == null || lowestList.size() <= 0) continue;
						for (BudgetTypes lowest : lowestList) {
							detail = setTypesInfo(lowest, chren.getTypeId());
							result.add(detail);
						}
					}
				}
			}
			return result;
		}
		return null;
	}

	private BudgetSubDto setTypesInfo(BudgetTypes bt, String parentTypeId) {
		BudgetSubDto detail = new BudgetSubDto();
		detail.setTypeId(bt.getTypeId());
		detail.setTypeName(bt.getTypeName());
		detail.setTypes(bt.getTypes());
		detail.setTypeNo(bt.getTypeNo());
		detail.setParentTypeId(parentTypeId);
		return detail;
	}
}